/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package controladoresJpa;

import controladoresJpa.exceptions.IllegalOrphanException;
import controladoresJpa.exceptions.NonexistentEntityException;
import controladoresJpa.exceptions.PreexistingEntityException;
import java.io.Serializable;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import model.Relacionamento;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Persistence;
import model.Entidade;
import model.AtributoMER;
import model.DicionarioMR;
import model.AssociacaoTabelaAtributo;
import model.Tabela;

/**
 * Módulo MR
 * Classe de Entidade do Banco de Dados, gerada automaticamente, porém com certas modificações
 * @author Eduardo, Maylon e Kamilla
 */
public class TabelaJpaController implements Serializable {

    public TabelaJpaController(EntityManagerFactory emf) {
        this.emf = emf;
    }
    private EntityManagerFactory emf = null;

    public TabelaJpaController(){
    if(emf==null)
        emf = Persistence.createEntityManagerFactory("unb-gama-threedsPU");
            }
    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Tabela tabela) throws PreexistingEntityException, Exception {
        if (tabela.getRelacionamentoList() == null) {
            tabela.setRelacionamentoList(new ArrayList<Relacionamento>());
        }
        if (tabela.getEntidadeList() == null) {
            tabela.setEntidadeList(new ArrayList<Entidade>());
        }
        if (tabela.getAtributoMERList() == null) {
            tabela.setAtributoMERList(new ArrayList<AtributoMER>());
        }
        if (tabela.getDicionarioMRList() == null) {
            tabela.setDicionarioMRList(new ArrayList<DicionarioMR>());
        }
        if (tabela.getAssociacaoTabelaAtributoList() == null) {
            tabela.setAssociacaoTabelaAtributoList(new ArrayList<AssociacaoTabelaAtributo>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            List<Relacionamento> attachedRelacionamentoList = new ArrayList<Relacionamento>();
            for (Relacionamento relacionamentoListRelacionamentoToAttach : tabela.getRelacionamentoList()) {
                relacionamentoListRelacionamentoToAttach = em.getReference(relacionamentoListRelacionamentoToAttach.getClass(), relacionamentoListRelacionamentoToAttach.getNome());
                attachedRelacionamentoList.add(relacionamentoListRelacionamentoToAttach);
            }
            tabela.setRelacionamentoList(attachedRelacionamentoList);
            List<Entidade> attachedEntidadeList = new ArrayList<Entidade>();
            for (Entidade entidadeListEntidadeToAttach : tabela.getEntidadeList()) {
                entidadeListEntidadeToAttach = em.getReference(entidadeListEntidadeToAttach.getClass(), entidadeListEntidadeToAttach.getNome());
                attachedEntidadeList.add(entidadeListEntidadeToAttach);
            }
            tabela.setEntidadeList(attachedEntidadeList);
            List<AtributoMER> attachedAtributoMERList = new ArrayList<AtributoMER>();
            for (AtributoMER atributoMERListAtributoMERToAttach : tabela.getAtributoMERList()) {
                atributoMERListAtributoMERToAttach = em.getReference(atributoMERListAtributoMERToAttach.getClass(), atributoMERListAtributoMERToAttach.getNome());
                attachedAtributoMERList.add(atributoMERListAtributoMERToAttach);
            }
            tabela.setAtributoMERList(attachedAtributoMERList);
            List<DicionarioMR> attachedDicionarioMRList = new ArrayList<DicionarioMR>();
            for (DicionarioMR dicionarioMRListDicionarioMRToAttach : tabela.getDicionarioMRList()) {
                dicionarioMRListDicionarioMRToAttach = em.getReference(dicionarioMRListDicionarioMRToAttach.getClass(), dicionarioMRListDicionarioMRToAttach.getId());
                attachedDicionarioMRList.add(dicionarioMRListDicionarioMRToAttach);
            }
            tabela.setDicionarioMRList(attachedDicionarioMRList);
            List<AssociacaoTabelaAtributo> attachedAssociacaoTabelaAtributoList = new ArrayList<AssociacaoTabelaAtributo>();
            for (AssociacaoTabelaAtributo associacaoTabelaAtributoListAssociacaoTabelaAtributoToAttach : tabela.getAssociacaoTabelaAtributoList()) {
                associacaoTabelaAtributoListAssociacaoTabelaAtributoToAttach = em.getReference(associacaoTabelaAtributoListAssociacaoTabelaAtributoToAttach.getClass(), associacaoTabelaAtributoListAssociacaoTabelaAtributoToAttach.getCodigo());
                attachedAssociacaoTabelaAtributoList.add(associacaoTabelaAtributoListAssociacaoTabelaAtributoToAttach);
            }
            tabela.setAssociacaoTabelaAtributoList(attachedAssociacaoTabelaAtributoList);
            em.persist(tabela);
            for (Relacionamento relacionamentoListRelacionamento : tabela.getRelacionamentoList()) {
                relacionamentoListRelacionamento.getTabelaList().add(tabela);
                relacionamentoListRelacionamento = em.merge(relacionamentoListRelacionamento);
            }
            for (Entidade entidadeListEntidade : tabela.getEntidadeList()) {
                entidadeListEntidade.getTabelaList().add(tabela);
                entidadeListEntidade = em.merge(entidadeListEntidade);
            }
            for (AtributoMER atributoMERListAtributoMER : tabela.getAtributoMERList()) {
                atributoMERListAtributoMER.getTabelaList().add(tabela);
                atributoMERListAtributoMER = em.merge(atributoMERListAtributoMER);
            }
            for (DicionarioMR dicionarioMRListDicionarioMR : tabela.getDicionarioMRList()) {
                dicionarioMRListDicionarioMR.getTabelaList().add(tabela);
                dicionarioMRListDicionarioMR = em.merge(dicionarioMRListDicionarioMR);
            }
            for (AssociacaoTabelaAtributo associacaoTabelaAtributoListAssociacaoTabelaAtributo : tabela.getAssociacaoTabelaAtributoList()) {
                Tabela oldNometabelaOfAssociacaoTabelaAtributoListAssociacaoTabelaAtributo = associacaoTabelaAtributoListAssociacaoTabelaAtributo.getNometabela();
                associacaoTabelaAtributoListAssociacaoTabelaAtributo.setNometabela(tabela);
                associacaoTabelaAtributoListAssociacaoTabelaAtributo = em.merge(associacaoTabelaAtributoListAssociacaoTabelaAtributo);
                if (oldNometabelaOfAssociacaoTabelaAtributoListAssociacaoTabelaAtributo != null) {
                    oldNometabelaOfAssociacaoTabelaAtributoListAssociacaoTabelaAtributo.getAssociacaoTabelaAtributoList().remove(associacaoTabelaAtributoListAssociacaoTabelaAtributo);
                    oldNometabelaOfAssociacaoTabelaAtributoListAssociacaoTabelaAtributo = em.merge(oldNometabelaOfAssociacaoTabelaAtributoListAssociacaoTabelaAtributo);
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findTabela(tabela.getNome()) != null) {
                throw new PreexistingEntityException("Tabela " + tabela + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Tabela tabela) throws IllegalOrphanException, NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Tabela persistentTabela = em.find(Tabela.class, tabela.getNome());
            List<Relacionamento> relacionamentoListOld = persistentTabela.getRelacionamentoList();
            List<Relacionamento> relacionamentoListNew = tabela.getRelacionamentoList();
            List<Entidade> entidadeListOld = persistentTabela.getEntidadeList();
            List<Entidade> entidadeListNew = tabela.getEntidadeList();
            List<AtributoMER> atributoMERListOld = persistentTabela.getAtributoMERList();
            List<AtributoMER> atributoMERListNew = tabela.getAtributoMERList();
            List<DicionarioMR> dicionarioMRListOld = persistentTabela.getDicionarioMRList();
            List<DicionarioMR> dicionarioMRListNew = tabela.getDicionarioMRList();
            List<AssociacaoTabelaAtributo> associacaoTabelaAtributoListOld = persistentTabela.getAssociacaoTabelaAtributoList();
            List<AssociacaoTabelaAtributo> associacaoTabelaAtributoListNew = tabela.getAssociacaoTabelaAtributoList();
            List<String> illegalOrphanMessages = null;
            if(associacaoTabelaAtributoListNew!=null)
            for (AssociacaoTabelaAtributo associacaoTabelaAtributoListOldAssociacaoTabelaAtributo : associacaoTabelaAtributoListOld) {
                if (!associacaoTabelaAtributoListNew.contains(associacaoTabelaAtributoListOldAssociacaoTabelaAtributo)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain AssociacaoTabelaAtributo " + associacaoTabelaAtributoListOldAssociacaoTabelaAtributo + " since its nometabela field is not nullable.");
                }
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            List<Relacionamento> attachedRelacionamentoListNew = new ArrayList<Relacionamento>();
            if(relacionamentoListNew!=null)
            for (Relacionamento relacionamentoListNewRelacionamentoToAttach : relacionamentoListNew) {
                relacionamentoListNewRelacionamentoToAttach = em.getReference(relacionamentoListNewRelacionamentoToAttach.getClass(), relacionamentoListNewRelacionamentoToAttach.getNome());
                attachedRelacionamentoListNew.add(relacionamentoListNewRelacionamentoToAttach);
            }
            relacionamentoListNew = attachedRelacionamentoListNew;
            tabela.setRelacionamentoList(relacionamentoListNew);
            List<Entidade> attachedEntidadeListNew = new ArrayList<Entidade>();
            if(entidadeListNew!=null)
            for (Entidade entidadeListNewEntidadeToAttach : entidadeListNew) {
                entidadeListNewEntidadeToAttach = em.getReference(entidadeListNewEntidadeToAttach.getClass(), entidadeListNewEntidadeToAttach.getNome());
                attachedEntidadeListNew.add(entidadeListNewEntidadeToAttach);
            }
            entidadeListNew = attachedEntidadeListNew;
            tabela.setEntidadeList(entidadeListNew);
            List<AtributoMER> attachedAtributoMERListNew = new ArrayList<AtributoMER>();
            if(atributoMERListNew!=null)
            for (AtributoMER atributoMERListNewAtributoMERToAttach : atributoMERListNew) {
                atributoMERListNewAtributoMERToAttach = em.getReference(atributoMERListNewAtributoMERToAttach.getClass(), atributoMERListNewAtributoMERToAttach.getNome());
                attachedAtributoMERListNew.add(atributoMERListNewAtributoMERToAttach);
            }
            atributoMERListNew = attachedAtributoMERListNew;
            tabela.setAtributoMERList(atributoMERListNew);
            List<DicionarioMR> attachedDicionarioMRListNew = new ArrayList<DicionarioMR>();
            if(dicionarioMRListNew!=null)
            for (DicionarioMR dicionarioMRListNewDicionarioMRToAttach : dicionarioMRListNew) {
                dicionarioMRListNewDicionarioMRToAttach = em.getReference(dicionarioMRListNewDicionarioMRToAttach.getClass(), dicionarioMRListNewDicionarioMRToAttach.getId());
                attachedDicionarioMRListNew.add(dicionarioMRListNewDicionarioMRToAttach);
            }
            dicionarioMRListNew = attachedDicionarioMRListNew;
            tabela.setDicionarioMRList(dicionarioMRListNew);
            List<AssociacaoTabelaAtributo> attachedAssociacaoTabelaAtributoListNew = new ArrayList<AssociacaoTabelaAtributo>();
            if(associacaoTabelaAtributoListNew!=null)
            for (AssociacaoTabelaAtributo associacaoTabelaAtributoListNewAssociacaoTabelaAtributoToAttach : associacaoTabelaAtributoListNew) {
                associacaoTabelaAtributoListNewAssociacaoTabelaAtributoToAttach = em.getReference(associacaoTabelaAtributoListNewAssociacaoTabelaAtributoToAttach.getClass(), associacaoTabelaAtributoListNewAssociacaoTabelaAtributoToAttach.getCodigo());
                attachedAssociacaoTabelaAtributoListNew.add(associacaoTabelaAtributoListNewAssociacaoTabelaAtributoToAttach);
            }
            associacaoTabelaAtributoListNew = attachedAssociacaoTabelaAtributoListNew;
            tabela.setAssociacaoTabelaAtributoList(associacaoTabelaAtributoListNew);
            tabela = em.merge(tabela);
            if(relacionamentoListOld!=null)
            for (Relacionamento relacionamentoListOldRelacionamento : relacionamentoListOld) {
                if (!relacionamentoListNew.contains(relacionamentoListOldRelacionamento)) {
                    relacionamentoListOldRelacionamento.getTabelaList().remove(tabela);
                    relacionamentoListOldRelacionamento = em.merge(relacionamentoListOldRelacionamento);
                }
            }
            if(relacionamentoListNew!=null)
            for (Relacionamento relacionamentoListNewRelacionamento : relacionamentoListNew) {
                if (!relacionamentoListOld.contains(relacionamentoListNewRelacionamento)) {
                    relacionamentoListNewRelacionamento.getTabelaList().add(tabela);
                    relacionamentoListNewRelacionamento = em.merge(relacionamentoListNewRelacionamento);
                }
            }
            if(entidadeListOld!=null)
            for (Entidade entidadeListOldEntidade : entidadeListOld) {
                if (!entidadeListNew.contains(entidadeListOldEntidade)) {
                    entidadeListOldEntidade.getTabelaList().remove(tabela);
                    entidadeListOldEntidade = em.merge(entidadeListOldEntidade);
                }
            }
            if( entidadeListNew!=null)
            for (Entidade entidadeListNewEntidade : entidadeListNew) {
                if (!entidadeListOld.contains(entidadeListNewEntidade)) {
                    entidadeListNewEntidade.getTabelaList().add(tabela);
                    entidadeListNewEntidade = em.merge(entidadeListNewEntidade);
                }
            }
            if(atributoMERListOld!=null)
            for (AtributoMER atributoMERListOldAtributoMER : atributoMERListOld) {
                if (!atributoMERListNew.contains(atributoMERListOldAtributoMER)) {
                    atributoMERListOldAtributoMER.getTabelaList().remove(tabela);
                    atributoMERListOldAtributoMER = em.merge(atributoMERListOldAtributoMER);
                }
            }
            if(atributoMERListNew!=null)
            for (AtributoMER atributoMERListNewAtributoMER : atributoMERListNew) {
                if (!atributoMERListOld.contains(atributoMERListNewAtributoMER)) {
                    atributoMERListNewAtributoMER.getTabelaList().add(tabela);
                    atributoMERListNewAtributoMER = em.merge(atributoMERListNewAtributoMER);
                }
            }
            if(dicionarioMRListOld!=null)
            for (DicionarioMR dicionarioMRListOldDicionarioMR : dicionarioMRListOld) {
                if (!dicionarioMRListNew.contains(dicionarioMRListOldDicionarioMR)) {
                    dicionarioMRListOldDicionarioMR.getTabelaList().remove(tabela);
                    dicionarioMRListOldDicionarioMR = em.merge(dicionarioMRListOldDicionarioMR);
                }
            }
            if(dicionarioMRListNew!=null)
            for (DicionarioMR dicionarioMRListNewDicionarioMR : dicionarioMRListNew) {
                if (!dicionarioMRListOld.contains(dicionarioMRListNewDicionarioMR)) {
                    dicionarioMRListNewDicionarioMR.getTabelaList().add(tabela);
                    dicionarioMRListNewDicionarioMR = em.merge(dicionarioMRListNewDicionarioMR);
                }
            }
            if(associacaoTabelaAtributoListNew!=null)
            for (AssociacaoTabelaAtributo associacaoTabelaAtributoListNewAssociacaoTabelaAtributo : associacaoTabelaAtributoListNew) {
                if (!associacaoTabelaAtributoListOld.contains(associacaoTabelaAtributoListNewAssociacaoTabelaAtributo)) {
                    Tabela oldNometabelaOfAssociacaoTabelaAtributoListNewAssociacaoTabelaAtributo = associacaoTabelaAtributoListNewAssociacaoTabelaAtributo.getNometabela();
                    associacaoTabelaAtributoListNewAssociacaoTabelaAtributo.setNometabela(tabela);
                    associacaoTabelaAtributoListNewAssociacaoTabelaAtributo = em.merge(associacaoTabelaAtributoListNewAssociacaoTabelaAtributo);
                    if (oldNometabelaOfAssociacaoTabelaAtributoListNewAssociacaoTabelaAtributo != null && !oldNometabelaOfAssociacaoTabelaAtributoListNewAssociacaoTabelaAtributo.equals(tabela)) {
                        oldNometabelaOfAssociacaoTabelaAtributoListNewAssociacaoTabelaAtributo.getAssociacaoTabelaAtributoList().remove(associacaoTabelaAtributoListNewAssociacaoTabelaAtributo);
                        oldNometabelaOfAssociacaoTabelaAtributoListNewAssociacaoTabelaAtributo = em.merge(oldNometabelaOfAssociacaoTabelaAtributoListNewAssociacaoTabelaAtributo);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                String id = tabela.getNome();
                if (findTabela(id) == null) {
                    throw new NonexistentEntityException("The tabela with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(String id) throws IllegalOrphanException, NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Tabela tabela;
            try {
                tabela = em.getReference(Tabela.class, id);
                tabela.getNome();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The tabela with id " + id + " no longer exists.", enfe);
            }
            List<String> illegalOrphanMessages = null;
            List<AssociacaoTabelaAtributo> associacaoTabelaAtributoListOrphanCheck = tabela.getAssociacaoTabelaAtributoList();
            for (AssociacaoTabelaAtributo associacaoTabelaAtributoListOrphanCheckAssociacaoTabelaAtributo : associacaoTabelaAtributoListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Tabela (" + tabela + ") cannot be destroyed since the AssociacaoTabelaAtributo " + associacaoTabelaAtributoListOrphanCheckAssociacaoTabelaAtributo + " in its associacaoTabelaAtributoList field has a non-nullable nometabela field.");
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            List<Relacionamento> relacionamentoList = tabela.getRelacionamentoList();
            for (Relacionamento relacionamentoListRelacionamento : relacionamentoList) {
                relacionamentoListRelacionamento.getTabelaList().remove(tabela);
                relacionamentoListRelacionamento = em.merge(relacionamentoListRelacionamento);
            }
            List<Entidade> entidadeList = tabela.getEntidadeList();
            for (Entidade entidadeListEntidade : entidadeList) {
                entidadeListEntidade.getTabelaList().remove(tabela);
                entidadeListEntidade = em.merge(entidadeListEntidade);
            }
            List<AtributoMER> atributoMERList = tabela.getAtributoMERList();
            for (AtributoMER atributoMERListAtributoMER : atributoMERList) {
                atributoMERListAtributoMER.getTabelaList().remove(tabela);
                atributoMERListAtributoMER = em.merge(atributoMERListAtributoMER);
            }
            List<DicionarioMR> dicionarioMRList = tabela.getDicionarioMRList();
            for (DicionarioMR dicionarioMRListDicionarioMR : dicionarioMRList) {
                dicionarioMRListDicionarioMR.getTabelaList().remove(tabela);
                dicionarioMRListDicionarioMR = em.merge(dicionarioMRListDicionarioMR);
            }
            em.remove(tabela);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Tabela> findTabelaEntities() {
        return findTabelaEntities(true, -1, -1);
    }

    public List<Tabela> findTabelaEntities(int maxResults, int firstResult) {
        return findTabelaEntities(false, maxResults, firstResult);
    }

    private List<Tabela> findTabelaEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Tabela.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Tabela findTabela(String id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Tabela.class, id);
        } finally {
            em.close();
        }
    }

    public int getTabelaCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Tabela> rt = cq.from(Tabela.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    
}
